from __future__ import with_statement

import sys
import os
import shutil
import unittest
import traceback
import server
from kineta import *


class TxnTests(unittest.TestCase):

    def setUp(self):
        self._dbdir = "db"
        if os.path.isdir(self._dbdir):
            shutil.rmtree(self._dbdir)
        self.open()

    def _open(self):
        db = FileDB(self._dbdir)
        db.set_bg_error_cb(self.bgerror)
        return db

    def open(self):
        self.db = self._open()

    def bgerror(self, exc_info):
        traceback.print_exception(*exc_info)

    def testTxnRollback(self):
        with self.db.begin() as txn:
            txn.insert("x", {"a": 1, "b": 2})
            raise Rollback()
        with self.db.select(table = "x", fields = ["a", "b"]) as reader:
            res = list(reader)
        self.assertEqual(len(res), 0)

    def testRollbackIdentity(self):
        with self.db.begin() as txn:
            txn.insert_bulk("x", ("a"), [[{"identity": True}]])
            with txn.select(table = "x", fields = "a") as reader:
                res = list(reader)
            self.assertEqual(len(res), 1)
            self.assertEqual(res[0], [1L])
            raise Rollback()
        self.db.insert_bulk("x", ("a"), [[{"identity": True}]])
        with self.db.select(table = "x", fields = "a") as reader:
            res = list(reader)
        self.assertEqual(len(res), 1)
        self.assertEqual(res[0], [1L])

    def testTxnCommit(self):
        with self.db.begin() as txn:
            txn.insert_bulk("x", ("a", "b"), [(1, 2), (3, 4), (5, 6)])
            self.assert_("x" in txn.list_tables())
        with self.db.select(table = "x", fields = ["a", "b"]) as reader:
            res = list(reader)
        self.assertEqual(len(res), 3)
        self.assertEqual(res[0], [1, 2])
        self.assertEqual(res[1], [3, 4])
        self.assertEqual(res[2], [5, 6])

    def testManualRollback(self):
        for i in xrange(2):
            txn = self.db.begin()
            ok = False
            try:
                txn.insert("x", {"a": 1, "b": 2})
                if i == 0:
                    raise Exception()
                ok = True
            except:
                pass
            finally:
                if not ok:
                    txn.rollback()
                else:
                    txn.commit()
            with self.db.select(table = "x", fields = ["a", "b"]) as reader:
                res = list(reader)
            if i == 0:
                self.assertEqual(len(res), 0)
            else:
                self.assertEqual(len(res), 1)

    def tearDown(self):
        self.db.close()


class TxnTestsRemote(TxnTests):

    def _open(self):
        return RemoteDB("http://localhost:20000/db")

    def open(self):
        self.server = server.TestServer()
        self.server.app.databases['db'].set_bg_error_cb(self.bgerror)
        self.db = self._open()

    def tearDown(self):
        self.server.quit()
        try:
            self.db.list_tables()
        except:
            pass
        self.db.close()
        self.server.join()
